﻿// WismedCalcTempFast.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。

#include <iostream>
#include <string>
#include <vector>
#include <windows.h>
#include <time.h>
#include <iostream>
#include "MathTools.h"
#include "CFastTempHome.h"

#define Data_INTERVAL_TIME (2)
#define COLLECT_DATA_SIZE (120)
typedef float (*TempBuffPoint)[4];


/*
 * 判断温度在一段时间内体温是否发生超过指定温度的变化
 *		times：时长，秒
 *		tempChange：温度变化量，摄氏度
 */
bool checkSensorIfOff(int times, float tempChange, bool temp_collect_data_full, int temp_collect_data_index, TempBuffPoint temp_collect_data_buf) {
	if (!temp_collect_data_full) {
		return false;
	}

	int loop = times / Data_INTERVAL_TIME;
	int i = 0;
	float limitTemp = tempChange;// OPENMODE_TEMP_DIFF_THRED;
	int beforeIndex = (temp_collect_data_index + COLLECT_DATA_SIZE - loop) % COLLECT_DATA_SIZE;
	if (((temp_collect_data_buf[beforeIndex][0] - temp_collect_data_buf[temp_collect_data_index][0]) > limitTemp)
		|| ((temp_collect_data_buf[beforeIndex][1] - temp_collect_data_buf[temp_collect_data_index][1]) > limitTemp)) {
		return true;
	}

	return false;
}

/*temp接口测试通过文件读取数据*/
void apiTempCheckByFile(const char* filePathIn, char* fileName) {
	//char *fileNameIn = (char*)"all.txt";
	char* fileNameIn = (char*)"testData.txt";

	//char *fileNameIn = (char*)"刘跃-test.txt";
	if (fileName != NULL) {
		fileNameIn = fileName;
	}

	CSavaCharData* m_pSaveData;
	char FileName[128];
	time_t curTime = time(NULL);
	struct tm* pTm = localtime(&curTime);
	sprintf(FileName, "%4d-%02d-%02d_%02d.%02d.%02d_%s_calc.txt",
		pTm->tm_year + 1900, pTm->tm_mon + 1, pTm->tm_mday, pTm->tm_hour, pTm->tm_min, pTm->tm_sec, fileNameIn);
	m_pSaveData = new CSavaCharData(FileName, (char*)"w+");

	// 算法初始化调用

	bool needInit = true;	// 根据自己的需求，在需要时初始化
	int vFlag = -1;

	int dataInterval = 2;	// 数据间隔，秒

	// 打开文件
	char filePath[1024 * 5];
	if (filePathIn != NULL) {
		sprintf(filePath, "%s\\%s", filePathIn, fileNameIn);
	}
	else {
		sprintf(filePath, "E:\\MatlabData\\2024年问题反馈处理\\20241218-家庭测温数据分析\\t13算法验证数据20241217\\%s", fileNameIn);
		sprintf(filePath, "E:\\MatlabData\\2024年问题反馈处理\\20241218-家庭测温数据分析\\20241221-家庭测温算法测试\\%s", fileNameIn);

		//sprintf(filePath, "F:\\MatlabData\\2024年问题反馈处理\\20241120-病房测温服务器监测数据分析-体温稳定性\\20241124\\2024.11.22-2024.11.24准确性长时间测试\\%s", fileNameIn);
		//sprintf(filePath, "F:\\MatlabData\\2024年问题反馈处理\\20241023-体温数据分析\\20241106-体温算法更新\\%s", fileNameIn);
		//sprintf(filePath, "F:\\MatlabData\\2024年问题反馈处理\\20241023-体温数据分析\\原始数据\\10mm胶贴样品人体测试数据\\%s", fileNameIn);

	}
	FILE* pFile = fopen(filePath, "r");
	int pointIndex = 0;
	int index = 0;

	int fast_flag = 0; // 是否快速升温，0：不进入，1：进入
	const float FastTemp_Threshold = 32.0f;
	int fast_timecnt = 0;
	const int EndOut_Stage = 0;			// 结束快速升温输出
	const int FixedOut_Stage = 1;		// 固定快速升温输出 持续3分钟
	const int ContinueOut_Stage = 2;	// 持续快速升温输出阶段 持续判断快速计算值与准确值大小
	int fase_time_start = EndOut_Stage;
	CFastTempHome fastTempHome;			// 家庭产品用快速升温算法
	bool jumpFastTemp = false;			// 是否主动退出快速升温算法

	float temp_collect_data_buf[COLLECT_DATA_SIZE][4];		//用于记录采集到的环境温度、体表温、温差、温度变化值
	int temp_collect_data_index = 0;			
	bool temp_collect_data_full = false;		//buff是否缓存满了

	if (pFile != NULL) {
		while (true) {
			int ir, red;
			double dData[8];
			int nRet = fscanf(pFile, "%lf %lf\r\n", &dData[1], &dData[2], &dData[3]); //dEcg *= 21000;
			double surfTemp = dData[1];
			double envTemp = dData[2];

			if (nRet == 2) {
				if (needInit) {
					needInit = !needInit;
					// 初始化快速升温算法
					fastTempHome.init();
					// 初始化调度
					fast_flag = 0;
					fast_timecnt = 0;
					jumpFastTemp = false;
					fase_time_start = EndOut_Stage;
					memset(temp_collect_data_buf, 0, sizeof(temp_collect_data_buf));
					temp_collect_data_index = 0;
					temp_collect_data_full = false;
				}

				if (index == 301) {
					puts("find break");
				}

				// 缓存最近COLLECT_DATA_SIZE*2秒的数据待用
				temp_collect_data_buf[temp_collect_data_index][0] = surfTemp;
				temp_collect_data_buf[temp_collect_data_index][1] = envTemp;
				temp_collect_data_buf[temp_collect_data_index][2] = surfTemp - envTemp;

				if (index > 0) {
					int lastIndex = temp_collect_data_index - 1;
					if (lastIndex < 0)
						lastIndex = COLLECT_DATA_SIZE - 1;
					temp_collect_data_buf[temp_collect_data_index][3] = temp_collect_data_buf[lastIndex][0] - surfTemp;
				}

				// 判断是否发生了温度脱落
				bool isSensorOff = checkSensorIfOff(20, 1.0f, temp_collect_data_full, temp_collect_data_index, temp_collect_data_buf);

				temp_collect_data_index++;
				if (temp_collect_data_index >= COLLECT_DATA_SIZE) {
					temp_collect_data_index = 0;
					temp_collect_data_full = true;
				}

				TempBuffPoint bufPoint = temp_collect_data_buf;
				int bufLen = 0;
				if (temp_collect_data_full)
					bufLen = COLLECT_DATA_SIZE;
				else
					bufLen = temp_collect_data_index;
				int bufStartIndex = 0;
				if (temp_collect_data_full)
					bufStartIndex = temp_collect_data_index;
				else
					bufStartIndex = 0;

				float showTemp = surfTemp;
				float ai_temp = -1;
				int flag_error = -1;
				int flag_stage = -1;
				float ai_ref_temp = 0;
				float last_tempini = 0;
				// 整体调度流程
				if (!jumpFastTemp) {
					// 快速升温算法

					FastTempResult_t fastRst = fastTempHome.wendu(surfTemp, envTemp, bufPoint, bufLen, bufStartIndex);

					ai_temp = fastRst.shijiwendu;
					int fast_sta = fastRst.using_fast_flag;
					ai_ref_temp = fastRst.chushiwendu_tb;	// 快速升温判定的初始温度
					bool fastTempIsStable = fastRst.flat_wendingxing == 1;	// 快速升温判定温度稳定
					flag_error = fastRst.flag_error;
					flag_stage = fastRst.stage;
					last_tempini = fastRst.last_tempini;
					if ((ai_ref_temp <= FastTemp_Threshold) && (fast_sta == 1) && (fast_flag == 0))//启动快速升温算法输出
					{
						fast_flag = 1;
						fast_timecnt = 0;
						fase_time_start = FixedOut_Stage;
					}
					else if ((ai_ref_temp > FastTemp_Threshold) && (fast_sta == 1)) {
						// 虽然内部认定可以进入快速升温，但是初始温度高于30摄氏度，暂时不引用，防止预测温度偏差过大
						jumpFastTemp = true;
					}
					else if (surfTemp > FastTemp_Threshold && fast_sta == 0) {
						// 体表温度已经高于30摄氏度，依然没有进入快速升温，跳出快速升温
						jumpFastTemp = true;
					}
					switch (fase_time_start)
					{
					case FixedOut_Stage:
						if (fast_timecnt < 90)//3分钟 2s*90
							fast_timecnt++;
						else
						{
							fase_time_start = ContinueOut_Stage;
							fast_timecnt = 0;
						}
						// **调整，在快速升温计时阶段，如果初始温度发生变化，重置3分钟计时时间** //
						if (ai_ref_temp != last_tempini)
						{
							fast_timecnt = 0;
						}
						// **调整结束** //
						if (flag_error == 1)
						{ 
							showTemp = ai_temp;
							// 在快速升温预测出结果前发生异常，初始化一次，从头再来
							fastTempHome.init();
						} 
						else if (flag_error == 2)
						{
							showTemp = surfTemp;
							jumpFastTemp = true;
						}
						break;
					case ContinueOut_Stage:
						if ((fabs(ai_temp - surfTemp) < 0.3) || fastTempIsStable)//相差在0.3度以内
						{
							fase_time_start = EndOut_Stage;
							jumpFastTemp = true;
						}
						if (flag_error != 0)
						{
							showTemp = surfTemp;
							jumpFastTemp = true;
						}
						break;
					default:
						break;
					}

					if (fast_flag == 1 && !jumpFastTemp) {
						//快速输出赋值
						showTemp = ai_temp;
					}
					else if (jumpFastTemp) {
						// todo 首次判断需要跳出快速升温，后面做温度切换后的过度优化

						// 显示稳定算法输出值
						showTemp = surfTemp;
						// todo 初始化快速升温算法
						fastTempHome.init();
						fast_flag = 0;
					}
					else {
						// 显示稳定算法输出值
						showTemp = surfTemp;
					}
				}
				else {
					fast_flag = 0;
				}

				if (isSensorOff) {
					showTemp = surfTemp;
					needInit = true;
				}
				// 为快速升温算法的进入提供另一种条件（低于32摄氏度如果没触发那就触发它）
				if (surfTemp < FastTemp_Threshold && jumpFastTemp) {
					jumpFastTemp = false;
				}

				char tmpBuf[512] = { 0 };
				sprintf(tmpBuf, "%lf %lf %lf %lf %d\n", surfTemp, envTemp, ai_temp, showTemp, fast_flag);	//
				char tmpBuf2[512] = { 0 };
				index++;
				sprintf(tmpBuf2, "%d:\t\t%lf %lf %lf %lf %d %d %d %lf\n", index, surfTemp, envTemp, ai_temp, showTemp, fast_flag, flag_error, flag_stage, last_tempini);	//
				m_pSaveData->writeData((unsigned char*)tmpBuf, strlen(tmpBuf));
				puts(tmpBuf2);
				m_pSaveData->fileFlush();
			}
			else {
				printf("文件读取结束.");
				fclose(pFile);
				break;
			}
		}
	}
	else {
		printf("文件不存在.\n");
	}
}


// 遍历目录并返回所有 .txt 文件
std::vector<std::string> ListFilesWithTxtExtension(const std::string& directory) {
	std::vector<std::string> txtFiles;
	WIN32_FIND_DATAA findFileData;
	HANDLE hFind = INVALID_HANDLE_VALUE;

	// 目录路径添加通配符 \*.txt
	std::string directorySearchPath = directory + "\\*.txt";

	hFind = FindFirstFileA(directorySearchPath.c_str(), &findFileData);

	if (hFind == INVALID_HANDLE_VALUE) {
		std::cerr << "Error: Invalid directory or no .txt files found." << std::endl;
		return txtFiles;
	}

	do {
		// 检查是否为目录，如果不是则加入结果
		if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
			txtFiles.push_back(findFileData.cFileName);
			// 完整目录为
			std::string fullPath = directory + "\\" + findFileData.cFileName;
			std::cout << fullPath << std::endl;
			printf("完整路径：%s\r\n", fullPath.data());
			apiTempCheckByFile(directory.data(), findFileData.cFileName);
		}
	} while (FindNextFileA(hFind, &findFileData) != 0);

	// 关闭句柄
	FindClose(hFind);

	return txtFiles;
}

int main()
{
	//system("pause");
	apiTempCheckByFile(NULL, NULL);
	system("pause");
	std::string directory = "E:\\VisualStudioWorkstation\\WismedCalcTempFast\\WismedCalcTempFast\\testData";  // 要遍历的目录
	ListFilesWithTxtExtension(directory);
	std::cout << "Hello World!\n";
	system("pause");
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门提示: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件
